package com.vonchange.headb.core.base;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.vonchange.headb.core.annotation.HeaEntity;
import com.vonchange.headb.core.annotation.HeaExclusion;
import com.vonchange.headb.core.annotation.HeaId;
import com.vonchange.headb.core.bean.ColumnCondition;
import com.vonchange.headb.core.bean.Entity;
import com.vonchange.headb.core.bean.EntityField;
import com.vonchange.headb.core.bean.Join;
import com.vonchange.headb.core.bean.SqlFragment;
import com.vonchange.headb.core.bean.TableSql;
import com.vonchange.headb.core.constant.HeaConstant;
import com.vonchange.headb.core.enums.HeaTime;
import com.vonchange.headb.core.enums.HeaType;
import com.vonchange.headb.core.enums.SearchOperator;
import com.vonchange.headb.core.exception.MyRuntimeException;
import com.vonchange.headb.utils.HBase;
import com.vonchange.headb.utils.clazz.HClassUtils;
import com.vonchange.headb.utils.config.HConfigUtil;
import com.vonchange.headb.utils.convert.HConvertUtils;
import com.vonchange.headb.utils.file.HFileUtils;
import com.vonchange.headb.utils.logger.HLogUtils;
import com.vonchange.headb.utils.map.HHashMap;
import com.vonchange.headb.utils.named.HNamedParameterUtils;
import com.vonchange.headb.utils.named.ParsedSql;
import com.vonchange.headb.utils.orm.HOrmUtil;
import com.vonchange.headb.utils.string.HStringUtils;
import com.vonchange.headb.utils.time.HDateUtils;
import com.vonchange.headb.utils.xml.HXmlUtils;

/**
 * 需要的基础方法
 * 
 * @author vonchange@163.com
 * @date 2015年10月9日 上午11:27:03
 * @since 1.0
 * @param <T>
 */
public abstract class HeaCore<T> extends HBase {

	/**
	 * 实体Map
	 */
	public static final Map<String, Entity> entityMap = new HHashMap<String, Entity>();

	public abstract Class<T> getEntityType();

	protected Class<T> entityType = getEntityType();

	protected String getEntityName() {
		return this.entityType.getSimpleName();
	}

	/**
	 * @desc 获取可以转换的时间格式
	 * @return 时间格式String数组
	 */
	private String[] getPattern() {
		File xmlPath = HConfigUtil.getConfigXmlFile();
		if(null==xmlPath){
			return new  String[]{"yyyy","yyyy-MM","yyyy-MM-dd","yyyy-MM-dd HH","yyyy-MM-dd HH:mm"};
		}
		HXmlUtils xmlUtils = new HXmlUtils(xmlPath);
		String[] pattern = xmlUtils.getPattern();
		return pattern;
	}

	/**
	 * 实例化该实体
	 * 
	 * @return 实体实例
	 */
	protected T getInstanceEntity() {
		T entity = null;
		try {
			entity = this.entityType.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return entity;
	}

	/**
	 * 初始化实体信息
	 * 
	 * @param clazz
	 *            实体类
	 */
	protected void initEntityInfo(Class<?> clazz) {
		String entityName = clazz.getSimpleName();
		File file = HFileUtils.getClassPath(clazz);
		long entityLastModified = file.lastModified();
		if (0 == entityLastModified) {
			throw MyRuntimeException.Instance(entityName, "文件未找到");
		}
		if (null != entityMap.get(entityName)) {
			Entity entityInfo = entityMap.get(entityName);
			if (entityInfo.getLastModified() != entityLastModified) {
				initEntity(clazz, entityName, entityLastModified);
			}
			return;
		}
		initEntity(clazz, entityName, entityLastModified);
	}

	private void initEntity(Class<?> clazz, String entityName, long entityLastModified) {
		logger.info(HLogUtils.format("初始化", entityName));
		Entity entity = new Entity();
		entity.setLastModified(entityLastModified);
		entity.setEntityName(entityName);
		String tableName=HOrmUtil.toSql(entityName);
		HeaEntity heaEntity= clazz.getAnnotation(HeaEntity.class);
		if(null!=heaEntity){
			if(HStringUtils.isNotNull(heaEntity.value())){
				tableName=heaEntity.value();
			}
		}
		entity.setTableName(tableName);
		Field[] fileds = clazz.getDeclaredFields();// 只有本类
		Map<String, EntityField> entityFieldMap = new HHashMap<String, EntityField>();
		for (Field field : fileds) {
			EntityField entityField = new EntityField();
			String fieldName = field.getName();
			entityField.setFieldName(fieldName);
			String columnName = HOrmUtil.toSql(fieldName);	
			Class<?> type = field.getType();
			entityField.setColumnName(columnName);
			entityField.setTypeName(type.getSimpleName());
			Boolean isBaseType = HClassUtils.isBaseType(type);
			entityField.setIsBaseType(isBaseType);
			if (isBaseType) {
				entityField.setIsColumn(true);
			}
			Annotation[] annotations = field.getAnnotations();
			for (Annotation annotation : annotations) {
				if (annotation instanceof HeaId) {
					entityField.setIsId(true);
					entity.setIdFieldName(fieldName);
					entity.setIdColumnName(columnName);
					entity.setIdType(type.getSimpleName());
					boolean auto = ((HeaId) annotation).auto();
					if (auto) {
						if (type.getSimpleName().equals("String")) {
							entity.setIdModel(HeaConstant.Entity.UUID);
						} else {
							entity.setIdModel(HeaConstant.Entity.INCID);
						}
					}
				}
				if (annotation instanceof HeaExclusion) {
					entityField.setIsColumn(false);
				}
			}
			entityFieldMap.put(fieldName, entityField);
		}
		entity.setFieldMap(entityFieldMap);
		entityMap.put(entityName, entity);
	}

	/**
	 * 获取字段的类型
	 * 
	 * @param filedName
	 *            字段名
	 * @param xmlUtils
	 * @return 类型名
	 */
	protected String getFieldType(String filedName) {
		String result = null;
		String entityName = getEntityName();
		Entity entityInfo = entityMap.get(entityName);
		if (filedName.startsWith("t.")) {
			filedName = filedName.substring(2);
			result = entityInfo.getFieldMap().get(filedName).getTypeName();
		} else {
			String alias = HStringUtils.substringBefore(filedName, ".");
			String field = HStringUtils.substringAfter(filedName, ".");
			Join join = getXml().getJoin(alias);
			String classPath = join.getClasspath();
			Class<?> clazz = HClassUtils.forName(classPath);
			initEntityInfo(clazz);
			String joinEntityName = clazz.getSimpleName();
			Entity joinEntityInfo = entityMap.get(joinEntityName);
			result = joinEntityInfo.getFieldMap().get(field).getTypeName();
		}
		return result;
	}

	/**
	 * 检查是否含空格：值不允许空格
	 * 
	 * @param value
	 * @return
	 */
	protected String CheckSpace(String value) {
		if (value.indexOf(HeaConstant.SPACE) != -1) {
			throw new MyRuntimeException("不允许包含空格!");
		}
		if (value.startsWith("_")) {
			value = value.substring(1, value.length());
		}
		return value;
	}

	private String replaceNum(String value) {
		return HStringUtils.replaceEach(value, HeaConstant.NumToSymbol.NUMS, HeaConstant.NumToSymbol.NUMREPLACE);
	}

	/**
	 * 处理key值
	 * 
	 * @param key
	 * @return 处理过的key
	 */
	protected String filterKey(String key) {
		return replaceNum(CheckSpace(key));
	}

	/**
	 * 转换成Date类型
	 * 
	 * @param value
	 * @return Date时间
	 */
	protected Date convertToDate(Object value) {
		if (value instanceof Date) {
			return (Date) value;
		}
		Date result = null;
		try {
			result = HDateUtils.parseDate(String.valueOf(value), getPattern());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 值转换成字段对应的类型
	 * 
	 * @param value
	 * @param type
	 * @param valueType
	 * @return 转换过的值
	 */
	protected Object convertValue(Object value, String type, String valueType) {
		if (null == type) {
			return value;
		}
		logger.info(HLogUtils.formatOL("类型", type + "对" + valueType));
		if (!valueType.equalsIgnoreCase(type)) {
			if (HeaType.String.getName().equalsIgnoreCase(type)) {
				value = HConvertUtils.toString(value);
				return value;
			}
			if (HeaType.Integer.getName().equalsIgnoreCase(type)) {
				value = HConvertUtils.toInteger(value);
				return value;
			}
			if (HeaType.Long.getName().equalsIgnoreCase(type)) {
				value = HConvertUtils.toLong(value);
				return value;
			}
			if (HeaType.Boolean.getName().equalsIgnoreCase(type)) {
				value = HConvertUtils.toBoolean(value);
				return value;
			}
			if (HeaType.Double.getName().equalsIgnoreCase(type)) {
				value = HConvertUtils.toDouble(value);
				return value;
			}
			if (HeaType.Float.getName().equalsIgnoreCase(type)) {
				value = HConvertUtils.toFloat(value);
				return value;
			}
			if (HeaType.Short.getName().equalsIgnoreCase(type)) {
				value = HConvertUtils.toShort(value);
				return value;
			}
			if (HeaType.Byte.getName().equalsIgnoreCase(type)) {
				value = HConvertUtils.toByte(value);
				return value;
			}
			if (HeaType.TimeStamp.getName().equalsIgnoreCase(type) || HeaType.DatetTme.getName().equalsIgnoreCase(type) || HeaType.Date.getName().equalsIgnoreCase(type)) {
				if (value instanceof String) {
					value = convertToDate(value);
				}
				return value;
			}
			if (HeaType.big_decimal.getName().equalsIgnoreCase(type) || HeaType.BigDecimal.getName().equalsIgnoreCase(type)) {
				if (!(value instanceof BigDecimal)) {
					value = HConvertUtils.toBigDecimal(value);
				}
				return value;
			}
		}
		return value;
	}

	/**
	 * 获取该实体的xmlUtils对象
	 * 
	 * @return xmlUtils对象
	 */
	protected HXmlUtils getXml() {
		File xml = getXmlFile(this.entityType);
		return new HXmlUtils(xml) ;
	}

	/**
	 * 根据classpath获取xmlUtils对象
	 * 
	 * @param classpath
	 * @return xmlUtils对象
	 */
	protected HXmlUtils getXmlByStrClassPath(String classpath) {
		String packageName=HStringUtils.substringBeforeLast(classpath, ".");
		String name=classpath.substring(packageName.length(), classpath.length());		
		File xmlFile=HFileUtils.getClassPath(packageName, name);
		return new HXmlUtils(xmlFile);
	}

	private File getXmlFile(Class<T> entityType) {
		String entityName = entityType.getSimpleName();
		File xmlPathFile = HFileUtils.getClassPathByClazz(entityType, entityName + ".xml");
		return xmlPathFile;
	}

	/**
	 * 分析key值
	 * 
	 * @param columnCondition
	 * @param key
	 * @param value
	 * @return 字段条件实体
	 */
	protected ColumnCondition analyzeKey(ColumnCondition columnCondition, String key, Object value) {
		// addColumn
		columnCondition.setValue(value);
		if (key.startsWith("(")) {
			columnCondition.setLeftBracket("(");
		}
		if (key.startsWith("|")) {
			columnCondition.setAndOr("or");
		}
		if (key.endsWith(")")) {
			columnCondition.setRightBracket(")");
		}
		key = key.replaceAll("\\(|\\||\\)", "");
		String[] keyWithType = key.split(HeaConstant.TAPESPT);
		if (keyWithType.length == 2) {
			columnCondition.setType(keyWithType[1]);
			key = keyWithType[0];
		}
		String[] keys = key.split(HeaConstant.MYSPACE);
		boolean queryFlag = judgeIfNeedQuery(keys, value);// 判断是否需要进行查询
		if (queryFlag) {
			columnCondition.setIfQuery(true);
			columnCondition = analyzeKeys(columnCondition, keys, value);
			// 转换类型
			if (columnCondition.getParameterNum() > 0) {
				List<Object> cookedValue = cookedValue(columnCondition);
				columnCondition.setCookedValue(cookedValue);
			}
			if (!columnCondition.getXmlSqlFlag()) {
				StringBuffer sqlFragment = new StringBuffer();
				sqlFragment.append(columnCondition.getLeftBracket()).append(HeaConstant.SPACE).append(columnCondition.getTableAs()).append(columnCondition.getColumnName()).append(HeaConstant.SPACE).append(columnCondition.getCondition()).append(HeaConstant.SPACE).append(columnCondition.getDirectValue()).append(HeaConstant.SPACE).append(columnCondition.getRightBracket()).append(HeaConstant.SPACE);
				columnCondition.setSqlFragment(sqlFragment.toString());
			}
		}
		return columnCondition;
	}

	/**
	 * 判断是否需要进行查询
	 * 
	 * @param keys
	 * @param value
	 * @return 是否需要进行查询
	 */
	private boolean judgeIfNeedQuery(String[] keys, Object value) {
		if (keys.length == 3 && keys[2].equals(HeaConstant.RX)) {
			return true;
		}
		if (keys.length == 2 && keys[1].equals(SearchOperator.sql.getAd())) {
			return true;
		}
		if (null != value && !HStringUtils.isBlank(value.toString())) {
			if (keys.length > 1) {
				return true;
			}
		}
		if (keys.length == 3 && keys[2].equals(HeaConstant.CK)) {
			throw new RuntimeException("传入值为空!请自行处理!");
		}
		return false;
	}

	/**
	 * 分析sql片段
	 * 
	 * @param sqlFragment
	 * @param value
	 * @return SqlFragment
	 */
	@SuppressWarnings("unchecked")
	private SqlFragment analyzeSqlFragment(String sqlFragment, Object value) {
		SqlFragment sqlFragmentBean = new SqlFragment();
		Object[] attrValue = null;
		if (value.getClass().isArray()) {
			attrValue = (Object[]) value;
		} else {
			attrValue = new Object[] { value };
		}
		List<Character> resultSql = new ArrayList<Character>();
		List<Object> params = new ArrayList<Object>();
		char[] sqlchars = sqlFragment.toCharArray();
		int paramCount = 0;
		int i = 0;
		while (i < sqlchars.length) {
			char statement = sqlchars[i];
			if (statement == '?') {
				Object paramValue = attrValue[paramCount];
				if (null != paramValue) {
					boolean flag = false;
					List<Object> resultList = new ArrayList<Object>();
					resultList.add(paramValue);
					Class<?> retType = paramValue.getClass();
					if (Collection.class.isAssignableFrom(retType)) {
						resultList = (List<Object>) paramValue;
						flag = true;
					} else if (retType.isArray()) {
						Object[] arrValue = (Object[]) paramValue;
						resultList = Arrays.asList(arrValue);
						flag = true;
					}
					if (flag && resultList.size() > 0) {
						String statementStr = HStringUtils.StrNums("?", ",", resultList.size());
						char[] chars = statementStr.toCharArray();
						for (char c : chars) {
							resultSql.add(c);
						}
						params.addAll(resultList);
					} else {
						resultSql.add(statement);
						params.add(resultList.get(0));
					}
				} else {
					resultSql.add(statement);
					params.add(paramValue);
				}
				paramCount++;
			} else {
				resultSql.add(statement);
			}
			i++;
		}
		StringBuffer sb = new StringBuffer();
		for (Character character : resultSql) {
			sb.append(character);
		}
		sqlFragmentBean.setSql(sb.toString());
		sqlFragmentBean.setParams(params);
		return sqlFragmentBean;
	}

	private ColumnCondition analyzeKeys(ColumnCondition columnCondition, String[] keys, Object value) {
		String fieldName = keys[0];
		String[] alisaFields = fieldName.split("\\.");
		if (alisaFields.length > 1) {
			fieldName = alisaFields[1];
			columnCondition.setTableAs(alisaFields[0] + ".");
		}
		String columnName = HOrmUtil.toSql(fieldName);
		String condition = keys[1];
		columnCondition.setFieldName(fieldName);
		// 获得类型
		String type = columnCondition.getType();
		if (null == type) {
			try {
				type = getFieldType(columnCondition.getTableAs() + columnCondition.getFieldName());
			} catch (Exception e) {
				logger.warn("could not resolve property(无法得到字段类型)");
				type = null;
			}
			columnCondition.setType(type);
		}
		columnCondition.setColumnName(columnName);
		if (null != value) {
			Class<?> retType = value.getClass();
			if (Collection.class.isAssignableFrom(retType)) {
				Collection<?> colValue = (Collection<?>) value;
				columnCondition.setValue(colValue.toArray());
				columnCondition.setParameterNum(colValue.size());
			} else if (retType.isArray()) {
				Object[] arrValue = (Object[]) value;
				columnCondition.setParameterNum(arrValue.length);
			}
		}
		if (SearchOperator.sql.getAd().equals(condition)) {
			columnCondition.setXmlSqlFlag(true);
			HXmlUtils xmlUtils = getXml();
			String sql = xmlUtils.getSql(columnCondition.getFieldName());
			if (null == value) {
				columnCondition.setParameterNum(0);
				columnCondition.setSqlFragment(sql);
			} else {
				SqlFragment sqlFragment = analyzeSqlFragment(sql, value);
				columnCondition.setSqlFragment(sqlFragment.getSql());
				columnCondition.setParameterNum(sqlFragment.getParams().size());
				columnCondition.setValue(sqlFragment.getParams().toArray());
				// 处理sql和 value
			}
			return columnCondition;
		}
		// 有几个参数就几个
		if (null == value || HeaConstant.NULLStr.equalsIgnoreCase(String.valueOf(value).trim())) {
			if (SearchOperator.eq.getAd().equals(condition)) {
				condition = SearchOperator.isNull.getAd();
				columnCondition.setCondition(SearchOperator.isNull.getSymbol());
				columnCondition.setDirectValue("");
				columnCondition.setParameterNum(0);
			}
			if (SearchOperator.neq.getAd().equals(condition)) {
				condition = SearchOperator.isNotNull.getAd();
				columnCondition.setCondition(SearchOperator.isNotNull.getSymbol());
				columnCondition.setDirectValue("");
				columnCondition.setParameterNum(0);
			}
			return columnCondition;
		}

		if (SearchOperator.eq.getAd().equals(condition)) {
			columnCondition.setCondition(SearchOperator.eq.getSymbol());
			return columnCondition;
		}
		if (SearchOperator.neq.getAd().equals(condition)) {
			columnCondition.setCondition(SearchOperator.neq.getSymbol());
			return columnCondition;
		}
		if (SearchOperator.gt.getAd().equals(condition)) {
			columnCondition.setCondition(SearchOperator.gt.getSymbol());
			return columnCondition;
		}
		if (condition.indexOf(SearchOperator.ge.getAd()) != -1) {
			condition = condition.replaceFirst(SearchOperator.ge.getAd(), "");// 替换ge
			columnCondition.setCondition(SearchOperator.ge.getSymbol());
			if (!"".equals(condition)) {
				columnCondition = extDateCondition(condition, "", false, columnCondition);
			}
			return columnCondition;
		}
		if (SearchOperator.lt.getAd().equals(condition)) {
			columnCondition.setCondition(SearchOperator.lt.getSymbol());
			return columnCondition;
		}
		if (condition.indexOf(SearchOperator.le.getAd()) != -1) {
			condition = condition.replaceFirst(SearchOperator.le.getAd(), "");
			columnCondition.setCondition(SearchOperator.le.getSymbol());
			if (!"".equals(condition)) {
				columnCondition = extDateCondition(condition, "", true, columnCondition);
			}
			return columnCondition;
		}

		if (condition.indexOf(SearchOperator.like.getAd()) != -1) {
			columnCondition.setCondition(SearchOperator.like.getSymbol());
			condition = condition.replaceFirst(SearchOperator.like.getAd(), "");
			columnCondition = extLikeCondition(condition, value, columnCondition);
			if (columnCondition.getTempFlag()) {
				columnCondition = extDateCondition(condition, "%", false, columnCondition);
			}
			return columnCondition;
		}
		if (condition.equals(SearchOperator.in.getAd())) {
			columnCondition.setCondition(SearchOperator.in.getSymbol());
			columnCondition.setDirectValue("(?)");
			return columnCondition;
		}
		if (condition.equals(SearchOperator.notIn.getAd())) {
			columnCondition.setCondition(SearchOperator.notIn.getSymbol());
			columnCondition.setDirectValue("(?)");
			return columnCondition;
		}
		if (condition.equals(SearchOperator.not.getAd())) {// 比如not 3 为!=3 or is
															// null
			columnCondition.setCondition(SearchOperator.not.getSymbol());
			columnCondition.setLeftBracket("(");
			columnCondition.setRightBracket(")");
			columnCondition.setDirectValue(HStringUtils.format(" ? or {0} is null", columnName));
			return columnCondition;
		}
		if (condition.indexOf(SearchOperator.notLike.getAd()) != -1) {// 不常用
			columnCondition.setCondition(SearchOperator.notLike.getSymbol());
			condition = condition.replaceFirst(SearchOperator.notLike.getAd(), "");
			columnCondition = extLikeCondition(condition, value, columnCondition);
			if (columnCondition.getTempFlag()) {
				columnCondition = extDateCondition(condition, "%", false, columnCondition);
			}
			return columnCondition;
		}
		if (SearchOperator.isNull.getAd().equals(condition)) {
			columnCondition.setCondition(SearchOperator.isNull.getSymbol());
			columnCondition.setDirectValue("");
			columnCondition.setParameterNum(0);
			return columnCondition;
		}
		if (SearchOperator.isNotNull.getAd().equals(condition)) {
			columnCondition.setCondition(SearchOperator.isNotNull.getSymbol());
			columnCondition.setDirectValue("");
			columnCondition.setParameterNum(0);
			return columnCondition;
		}

		if (HStringUtils.isEnglish(condition)) {// 比如 in
			columnCondition.setCondition(condition);
			return columnCondition;
		}
		throw new RuntimeException("本版本不再允许带符号条件传入!比如=,>换用eq,gt");
	}

	private List<Object> cookedValue(ColumnCondition columnCondition) {
		Object value = columnCondition.getValue();
		String type = columnCondition.getType();
		String valueType = null;
		Class<?> retType = value.getClass();
		Object[] values = new Object[] { value };
		if (retType.isArray()) {
			Object[] arrValue = (Object[]) value;
			values = arrValue;
			if (!columnCondition.getXmlSqlFlag()) {// 不是xml里的sql
				String prmStr = HStringUtils.StrNums("?", ",", columnCondition.getParameterNum());
				String directValueStr = columnCondition.getDirectValue();
				columnCondition.setDirectValue(directValueStr.replace("?", prmStr));
			}
		}
		if (values.length > 0) {
			valueType = values[0].getClass().getSimpleName();
		}
		List<Object> resultCol = new ArrayList<Object>();
		for (Object object : values) {
			resultCol.add(convertValue(object, type, valueType));
		}
		return resultCol;
	}

	private ColumnCondition extDateCondition(String extCondtion, String like, boolean addOne, ColumnCondition columnCondition) {
		Object value = columnCondition.getValue();
		if (HeaTime.day.getName().equals(extCondtion) || HeaTime.day.getAd().equals(extCondtion)) {
			Date date = convertToDate(value);
			if (addOne) {
				date = HDateUtils.addDays(date, 1);
				columnCondition.setCondition("<");
			}
			columnCondition.setDirectValue("'" + HDateUtils.format("yyyy-MM-dd", date) + like + "'");
			columnCondition.setParameterNum(0);
			return columnCondition;
		}
		if (HeaTime.month.getName().equals(extCondtion) || HeaTime.month.getAd().equals(extCondtion)) {
			Date date = convertToDate(value);
			if (addOne) {
				date = HDateUtils.addMonths(date, 1);
				columnCondition.setCondition("<");
			}
			columnCondition.setDirectValue("'" + HDateUtils.format("yyyy-MM", date) + like + "'");
			columnCondition.setParameterNum(0);
			return columnCondition;
		}
		if (HeaTime.year.getName().equals(extCondtion) || HeaTime.year.getAd().equals(extCondtion)) {
			Date date = convertToDate(value);
			if (addOne) {
				date = HDateUtils.addYears(date, 1);
				columnCondition.setCondition("<");
			}
			columnCondition.setDirectValue("'" + HDateUtils.format("yyyy", date) + like + "'");
			columnCondition.setParameterNum(0);
			return columnCondition;
		}
		if (HeaTime.hour.getName().equals(extCondtion) || HeaTime.hour.getAd().equals(extCondtion)) {
			Date date = convertToDate(value);
			if (addOne) {
				date = HDateUtils.addHours(date, 1);
				columnCondition.setCondition("<");
			}
			columnCondition.setDirectValue("'" + HDateUtils.format("yyyy-MM-dd HH", date) + like + "'");
			columnCondition.setParameterNum(0);
			return columnCondition;
		}
		if (HeaTime.minute.getName().equals(extCondtion) || HeaTime.minute.getAd().equals(extCondtion)) {
			Date date = convertToDate(value);
			if (addOne) {
				date = HDateUtils.addMinutes(date, 1);
				columnCondition.setCondition("<");
			}
			columnCondition.setDirectValue("'" + HDateUtils.format("yyyy-MM-dd HH:mm", date) + like + "'");
			columnCondition.setParameterNum(0);
			return columnCondition;
		}

		if (HeaTime.second.getName().equals(extCondtion) || HeaTime.second.getAd().equals(extCondtion)) {
			Date date = convertToDate(value);
			if (addOne) {
				date = HDateUtils.addSeconds(date, 1);
				columnCondition.setCondition("<");
			}
			columnCondition.setDirectValue("'" + HDateUtils.format("yyyy-MM-dd HH:mm:ss", date) + like + "'");
			columnCondition.setParameterNum(0);
			return columnCondition;
		}
		return columnCondition;
	}

	private ColumnCondition extLikeCondition(String extCondtion, Object value, ColumnCondition columnCondition) {
		if ("".equals(extCondtion)) {// 默认左模糊查询
			String valueString = String.valueOf(value);
			if (valueString.indexOf("%") == -1) {
				value = valueString + "%";
			}
			columnCondition.setType(HeaType.String.name());
			columnCondition.setValue(value);
			columnCondition.setTempFlag(false);
			return columnCondition;
		}
		if ("%".equals(extCondtion)) {// 右模糊查询 5like
			String valueString = String.valueOf(value);
			if (valueString.indexOf("%") == -1) {
				value = "%" + valueString;
			}
			columnCondition.setType(HeaType.String.name());
			columnCondition.setValue(value);
			columnCondition.setTempFlag(false);
			return columnCondition;
		}
		if ("%%".equals(extCondtion)) {// 模糊查询 5like5
			String valueString = String.valueOf(value);
			if (valueString.indexOf("%") == -1) {
				value = "%" + valueString + "%";
			}
			columnCondition.setType(HeaType.String.name());
			columnCondition.setValue(value);
			columnCondition.setTempFlag(false);
			return columnCondition;
		}
		return columnCondition;
	}

	/**
	 * 获取字段sql中的alias
	 * 
	 * @param aliasMapInColumn
	 * @param xmlUtils
	 * @return Map
	 */
	protected Map<String, String> getColumnMappingAlias(Map<String, Boolean> aliasMapInColumn) {
		Map<String, String> aliasMap = new HHashMap<String, String>();
		for (Entry<String, Boolean> entry : aliasMapInColumn.entrySet()) {
			String alias = entry.getKey();
			Join join = getXml().getJoin(alias);
			aliasMap.put(alias, join.getField());
		}
		return aliasMap;
	}

	/**
	 * 获得joinSql
	 * 
	 * @param joinSqlMap
	 * @return joinSql
	 */
	protected String getJoinSql(HHashMap<Integer, String> joinSqlMap) {
		StringBuffer joinSqlBuffer = new StringBuffer();
		int level = joinSqlMap.size();
		if (level > 0) {
			for (int i = 1; i <= level; i++) {
				joinSqlBuffer.append(joinSqlMap.get(i));
			}
			return joinSqlBuffer.toString();
		}
		return "";
	}

	/**
	 * 分析aliasMap
	 * 
	 * @param aliasMap
	 * @param xmlUtils
	 * @param joinSqlMap
	 */
	protected void analyzeAliasMap(ConcurrentHashMap<String, Boolean> aliasMap, HHashMap<Integer, String> joinSqlMap) {
		if (aliasMap.isEmpty()) {
			return;
		}
		for (Entry<String, Boolean> entry : aliasMap.entrySet()) {
			String alias = entry.getKey();
			Boolean flag = entry.getValue();
			if (!flag) {
				Join join = getXml().getJoin(alias);
				Integer level = join.getLevel();
				StringBuffer joinSqlBuffer = new StringBuffer();
				if (joinSqlMap.get(level) != null) {
					joinSqlBuffer.append(joinSqlMap.get(level));
				}
				joinSqlBuffer.append(HeaConstant.SPACE).append(join.getJoinSql()).append(HeaConstant.SPACE);
				joinSqlMap.set(level, joinSqlBuffer.toString());
				aliasMap.put(alias, true);
				if (join.getLevel() > 1) {
					String dependAlias = getXml().getDependAliasByField(join.getDependField());
					if (null == aliasMap.get(dependAlias)) {
						aliasMap.put(dependAlias, false);
						analyzeAliasMap(aliasMap, joinSqlMap);
					}
				}
			}

		}
	}

	/**
	 * 获得排序sql
	 * 
	 * @param value
	 * @param xmlUtils
	 * @return 排序sql
	 */
	protected String getOrderSql(String value) {
		value = CheckSpace(value);
		if (value.endsWith("_sql")) {
			String id = value.substring(0, value.length() - 4);
			return getXml().getSql(id);
		}
		if (value.endsWith("_desc")) {
			value = value.replace("_desc", " desc");
		}
		value = value.replace("8", ".");
		/*
		 * if(value.indexOf(".")==-1){ value="t."+value; }
		 */
		return HOrmUtil.toSql(value);
	}

	/**
	 * 获取排序sql的List
	 * 
	 * @param orderSqlList
	 * @param value
	 * @param xmlUtils
	 * @return 排序sql的List
	 */
	protected List<String> getOrder(List<String> orderSqlList, Object value) {
		if (value instanceof String) {
			String orderValue = (String) value;
			orderSqlList.add(getOrderSql(orderValue));
		}
		if (value instanceof String[]) {
			for (String str : (String[]) value) {
				orderSqlList.add(getOrderSql(str));
			}
		}
		return orderSqlList;
	}

	/**
	 * 获取表的sql
	 * 
	 * @param orgTableSql
	 * @param viewParams
	 * @return 表的sql
	 */
	protected TableSql getTableSql(String orgTableSql, Map<String, Object> viewParams) {
		TableSql tableSql = new TableSql();
		List<Object> params = new ArrayList<Object>();
		tableSql.setOrgTableSql(orgTableSql);
		List<String> heaViewList = getHeaView(orgTableSql);
		if (heaViewList.size() == 0) {
			tableSql.setTargetTableSql(orgTableSql);
			tableSql.setParams(params);
			return tableSql;
		}
		// 存在sql
		List<String> heaViewSqlList = new ArrayList<String>();
		for (String heaViewName : heaViewList) {
			String heaViewAliasName = HStringUtils.substringAfterLast(heaViewName, " ");
			String heaViewSql = getHeaViewSql(heaViewAliasName);
			heaViewSqlList.add("(" + heaViewSql + ") " + heaViewAliasName);
		}
		String targetTableSql = HStringUtils.replaceEach(orgTableSql, heaViewList.toArray(new String[heaViewList.size()]), heaViewSqlList.toArray(new String[heaViewSqlList.size()]));
		ParsedSql parsedSql = HNamedParameterUtils.parserSqlStatement(targetTableSql);
		String tableSqlStr = HNamedParameterUtils.substituteNamedParams(parsedSql, viewParams);
		tableSql.setTargetTableSql(tableSqlStr);
		params.addAll(HNamedParameterUtils.buildValueArray(parsedSql, viewParams));
		tableSql.setParams(params);
		// 获得视图
		return tableSql;
	}

	/**
	 * 替换HeaView
	 * 
	 * @param cudSql
	 * @return
	 */
	protected String getCUDSql(String cudSql) {
		List<String> heaViewList = getHeaView(cudSql);
		if (heaViewList.size() == 0) {
			return cudSql;
		}
		List<String> heaViewSqlList = new ArrayList<String>();
		for (String heaViewName : heaViewList) {
			String heaViewAliasName = HStringUtils.substringAfterLast(heaViewName, " ");
			String heaViewSql = getHeaViewSql(heaViewAliasName);
			heaViewSqlList.add("(" + heaViewSql + ") " + heaViewAliasName);
		}
		String targetTableSql = HStringUtils.replaceEach(cudSql, heaViewList.toArray(new String[heaViewList.size()]), heaViewSqlList.toArray(new String[heaViewSqlList.size()]));
		return targetTableSql;
	}

	private String getHeaViewSql(String heaViewAliasName) {
		HXmlUtils xmlUtils = getXml();
		if (heaViewAliasName.equals("t")) {
			return xmlUtils.getView();
		}
		Join join = xmlUtils.getJoin(heaViewAliasName);
		String classpath = join.getClasspath();
		HXmlUtils viewXmlUtils = getXmlByStrClassPath(classpath);
		return viewXmlUtils.getView();
	}

	private static List<String> getHeaView(String orgTableSql) {
		List<String> heaViewList = new ArrayList<String>();
		Matcher m = Pattern.compile("Hea([\\w]*[ ]*[\\w]*)").matcher(orgTableSql);
		while (m.find()) {
			String group = m.group();
			heaViewList.add(group);
		}
		return heaViewList;
	}

}
